#!/usr/bin/python3

# This file is part of Cockpit.
#
# Copyright (C) 2015 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.

import parent
from storagelib import *
from testlib import *


@skipImage("UDisks doesn't have support for iSCSI", "debian-stable", "debian-testing",
           "ubuntu-2004", "ubuntu-stable", "arch")
class TestStorageISCSI(StorageCase):

    def testISCSI(self):
        m = self.machine
        b = self.browser
        b.wait_timeout(120)

        # ensure that we generate a /etc/iscsi/initiatorname.iscsi
        m.execute("systemctl start iscsid && systemctl stop iscsid")

        target_iqn = "iqn.2015-09.cockpit.lan"
        initiator_iqn = "iqn.2015-10.cockpit.lan"

        # Increase the iSCSI timeouts for heavy load during our testing
        self.sed_file(r"s|^\(node\..*log.*_timeout = \).*|\1 60|", "/etc/iscsi/iscsid.conf")

        # Setup a iSCSI target with authentication for discovery and join
        #
        # HACK - some versions of targetcli crash when TERM is not set
        #        and stdout is not a tty.
        #
        #        https://bugzilla.redhat.com/show_bug.cgi?id=1441121

        m.execute("""
                  export TERM=dumb
                  targetcli /backstores/ramdisk create test 50M
                  targetcli /iscsi set discovery_auth enable=1 userid=admin password=foobar
                  targetcli /iscsi create %(tgt)s
                  targetcli /iscsi/%(tgt)s/tpg1/luns create /backstores/ramdisk/test
                  targetcli /iscsi/%(tgt)s/tpg1 set attribute authentication=1
                  targetcli /iscsi/%(tgt)s/tpg1/acls create %(ini)s
                  targetcli /iscsi/%(tgt)s/tpg1/acls/%(ini)s set auth userid=admin password=barfoo
                  """ % {"tgt": target_iqn, "ini": initiator_iqn})
        # m.execute("targetcli ls")

        self.login_and_go("/storage")

        # Set initiator IQN
        orig_iqn = m.execute("sed </etc/iscsi/initiatorname.iscsi -e 's/^.*=//'").rstrip()
        b.click('#edit-iscsi')
        self.dialog(expect={"name": orig_iqn},
                    values={"name": initiator_iqn})
        new_iqn = m.execute("sed </etc/iscsi/initiatorname.iscsi -e 's/^.*=//'").rstrip()
        self.assertEqual(new_iqn, initiator_iqn)

        # Access the target

        b.click('#add-iscsi-portal')

        self.dialog_wait_open()
        self.dialog_set_val("address", "127.0.0.1")
        self.dialog_set_val("username", "admin")
        self.dialog_set_val("password", "foobar")
        self.dialog_apply()
        # The dialog closes and a new dialog opens but we can't get
        # between that, so we just wait for the new fields to
        # appear.
        b.wait_visible(self.dialog_field("target"))
        b.wait_in_text(self.dialog_field("target"), target_iqn)
        self.dialog_apply()
        # Login will fail and a new dialog opens
        b.wait_visible(self.dialog_field("username"))
        self.dialog_wait_val("username", "admin")
        self.dialog_wait_val("password", "foobar")
        self.dialog_set_val("password", "barfoo")
        self.dialog_apply()
        self.dialog_wait_close()

        b.wait_in_text('#iscsi-sessions', target_iqn)
        b.wait_in_text('#drives', "LIO-ORG test")

        # Make a filesystem on it to prove that the disk really works.

        b.click('#drives .sidepanel-row:contains("LIO-ORG test")')
        b.wait_visible('#storage-detail')
        self.content_row_wait_in_col(1, 2, "Unrecognized data")
        self.content_row_action(1, "Format")
        self.dialog({"type": "ext4",
                     "name": "FILESYSTEM",
                     "mount_point": "/data"})
        self.content_row_wait_in_col(1, 2, "ext4 filesystem")
        # _netdev should have been prefilled
        self.content_tab_wait_in_info(1, 1, "Mount point", "_netdev")

        # Add the target a second time, just to check that the sorting function works
        b.click('#storage-detail a.pf-c-breadcrumb__link')
        b.wait_visible('#storage')
        b.click('#add-iscsi-portal')
        self.dialog_wait_open()
        self.dialog_set_val("address", "172.27.0.15")
        self.dialog_set_val("username", "admin")
        self.dialog_set_val("password", "foobar")
        self.dialog_apply()
        # The dialog closes and a new dialog opens but we can't get
        # between that, so we just wait for the new fields to
        # appear.
        b.wait_visible(self.dialog_field("target"))
        b.wait_in_text(self.dialog_field("target"), target_iqn)
        self.dialog_apply()
        # Login will fail and a new dialog opens
        b.wait_visible(self.dialog_field("username"))
        self.dialog_wait_val("username", "admin")
        self.dialog_wait_val("password", "foobar")
        self.dialog_set_val("password", "barfoo")
        self.dialog_apply()
        self.dialog_wait_close()

        b.wait_in_text('#iscsi-sessions', "172.27.0.15")

        b.click('#iscsi-sessions .toggle-armed')
        b.click('#iscsi-sessions .sidepanel-row:contains(127.0.0.1) button.pf-m-danger')
        b.wait_not_present('#iscsi-sessions .sidepanel-row:contains(127.0.0.1)')

        b.click('#iscsi-sessions .toggle-armed')
        b.click('#iscsi-sessions .sidepanel-row:contains(172.27.0.15) button.pf-m-danger')
        b.wait_not_present('#iscsi-sessions .sidepanel-row:contains(172.27.0.15)')

        b.wait_not_in_text('#drives', "LIO-ORG test")


if __name__ == '__main__':
    test_main()
